

import Foundation
import AVFoundation
import UIKit

class QRScanner: NSObject {
    
    static let shared = QRScanner()
    private let captureSession = AVCaptureSession()
    private let videoPreviewLayer = AVCaptureVideoPreviewLayer()
    private var device = AVCaptureDevice.default(for: .video)
    private var handleCompleted: ((String) -> ())? = nil
    // 有效扫码区域
    private let area = CGPoint(x: UIScreen.main.bounds.size.width/6, y: UIScreen.main.bounds.size.height/2-UIScreen.main.bounds.size.width*1/3-30)
    private let width = UIScreen.main.bounds.size.width * 2 / 3
    
    private override init() {
        super.init()
        AVCaptureDevice.requestAccess(for: AVMediaType.video) { (isSuccess) in
            if isSuccess {
                self.prepare()
            } else {
                print("无权访问摄像机")
            }
        }
    }
    func cameraWithPostion(position:AVCaptureDevice.Position){
        let devices = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: .video, position: position)
        let devicess = devices.devices
        for device in devicess {
            if(device.position == position){
                self.device = device
            }
        }
    }
    var factorNum:CGFloat = 1
    func factor(_ number:CGFloat,_ isCancel:Bool = false) -> CGFloat{
        device?.unlockForConfiguration()
        do {
            try device!.lockForConfiguration()
        } catch _ {
            NSLog("Error: lockForConfiguration.");
        }
        print("当前缩放系数是：",device!.videoZoomFactor)
        if #available(iOS 11.0, *) {
            if(number <= device!.maxAvailableVideoZoomFactor && number >= 1){
                if isCancel {
                    device?.videoZoomFactor = number
                }else{
                    device?.ramp(toVideoZoomFactor: number, withRate: 1000)
                }
                return number
            }
        } else {
            // Fallback on earlier versions
        }
        if #available(iOS 11.0, *) {
            if(number > device!.maxAvailableVideoZoomFactor){
                factorNum = device!.maxAvailableVideoZoomFactor
                return factorNum
            }else{
                factorNum = 1
                return factorNum
            }
        } else {
            // Fallback on earlier versions
        }
        return 1
    }
    private func prepare() {
        // 前置摄像头
        // QRScanner.shared.cameraWithPostion(position: .front)
        guard let deviceInput = try? AVCaptureDeviceInput(device: device!) else {
            print("发生错误")
            return
        }
        // 创建数据输出流
        let metadataOutput = AVCaptureMetadataOutput()
        let screen = UIScreen.main.bounds.size
        metadataOutput.rectOfInterest = CGRect(x: area.y/screen.height, y: area.x/screen.width, width: width/screen.height, height: width/screen.width)
        metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
        // 创建设备输出流
        let videoDataOutput = AVCaptureVideoDataOutput()
        videoDataOutput.setSampleBufferDelegate(self, queue: DispatchQueue.main)
        // 会话采集率
        captureSession.sessionPreset = .high
        // 添加数据输出流到会话对象
        captureSession.addOutput(metadataOutput)
        // 添加设备输出流到会话对象
        captureSession.addOutput(videoDataOutput)
        // 添加设备输入流到会话对象
        captureSession.addInput(deviceInput)
        // 设置数据输出类型
        metadataOutput.metadataObjectTypes = [
            .qr,        // 二维码
            .ean13,     // 条形码
            .ean8,      // 条形码
            .code128    // 条形码
        ]
        videoPreviewLayer.session = captureSession
        videoPreviewLayer.videoGravity = .resizeAspectFill
    }
    
    func scan(design: @escaping (_ previewLayer: CALayer)->()) -> Self {
        design(videoPreviewLayer)
        startRunning()
        return self
    }
    
    func completed(aCompleted: @escaping (_ value: String)->()) {
        self.handleCompleted = aCompleted
    }
    
    func startRunning() {
        captureSession.startRunning()
    }
    
    func stopRunning() {
        captureSession.stopRunning()
    }
}

extension QRScanner: AVCaptureMetadataOutputObjectsDelegate {
    
    func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
        guard metadataObjects.count>0 else{
            return
        }
        stopRunning()
        guard let stringValue = metadataObjects.first!.value(forKey: "stringValue") as? String else {
            return
        }
        handleCompleted?(stringValue)
    }
}

extension QRScanner: AVCaptureVideoDataOutputSampleBufferDelegate {
    func captureOutput(_ output: AVCaptureOutput, didDrop sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
    }
}
